import sys,json,os 
from func_timeout import func_set_timeout, FunctionTimedOut
import xlsxwriter
import time 
from tkinter import Tk, Button, Label, Checkbutton, IntVar, Frame
from tkinter.filedialog import askopenfilename, askdirectory

input_file_path = ''
output_dir = os.path.join(os.path.expanduser('~'), 'Documents')

def select_input_file():
    global input_file_path
    input_file_path = askopenfilename(filetypes=[('JSON 文件', '*.json')])
    if input_file_path:
        input_label.config(text=f'已选择输入文件: {os.path.basename(input_file_path)}')


def select_output_dir():
    global output_dir
    output_dir = askdirectory()
    if output_dir:
        output_label.config(text=f'已选择输出目录: {output_dir}')


def convert_json():
    global result_label, status_label, log_label
    if not input_file_path:
        # result_label.config(text='未选择输入文件')
        status_label.config(text='×', fg='red')
        log_label.config(text='未选择输入文件')
        return
    # result_label.config(text="开始转换 JSON 数据文件[%s]..." % (input_file_path))
    log_label.config(text="开始转换 JSON 数据文件[%s]..." % (input_file_path))
    try:
        data = json.load(open(input_file_path,"r",encoding='utf-8'))
        if type(data) != type([]):
            # result_label.config(text="错误,JSON 数据不是 List!")
            status_label.config(text='×', fg='red')
            log_label.config(text="错误,JSON 数据不是 List!")
        else:
            filename = os.path.basename(input_file_path)
            t = filename.split(".",1)
            outfilename = os.path.join(output_dir, t[0] + ".xlsx")
            workbook = xlsxwriter.Workbook(outfilename)
            worksheet = workbook.add_worksheet("sheet1")
            fields = ["_id"]
            for row in data:
                for key in row.keys():
                    if key not in fields:
                        fields.append(key)
            fields.sort()
            
            col_id = 0
            for field in fields:
                worksheet.write(0,col_id,field)
                col_id = col_id + 1
            row_id = 1
            col_id = 0
            for row in data:
                for field in fields:
                    if field == "_id":
                        worksheet.write(row_id,col_id,row_id+1)
                    if field in row.keys():
                        worksheet.write(row_id,col_id,row[field])
                    col_id = col_id + 1
                col_id = 0
                row_id = row_id + 1
            workbook.close()
            # result_label.config(text="数据转换成功,已经保存到:" + os.path.realpath(outfilename))
            status_label.config(text='✓', fg='green')
            log_label.config(text="数据转换成功,已经保存到:" + os.path.realpath(outfilename))
            if open_after_conversion.get():  
                os.startfile(os.path.realpath(outfilename))
    except Exception as err:
        # result_label.config(text=str(err) + "\n读取 文件失败,无法解析的JSON 文件")
        status_label.config(text='×', fg='red')
        log_label.config(text=str(err) + "\n读取 文件失败,无法解析的JSON 文件")
    # 移除自动关闭窗口的代码
    # print("3s 后自动关闭")
    # time.sleep(3)
    # root.destroy()

if __name__ == '__main__':
    root = Tk()
    root.title('JSON 转 XLSX')
    # 设置窗口大小为 400x300 像素
    root.geometry('400x400')

    open_after_conversion = IntVar()

    input_button = Button(root, text='选择 JSON 文件', command=select_input_file)
    input_button.pack(pady=10)
    input_label = Label(root, text='未选择输入文件')
    input_label.pack(pady=5)

    output_button = Button(root, text='选择输出目录', command=select_output_dir)
    output_button.pack(pady=10)
    output_label = Label(root, text=f'默认输出目录: {output_dir}')
    output_label.pack(pady=5)

    convert_frame = Frame(root)
    convert_button = Button(convert_frame, text='开始转换', command=convert_json)
    convert_button.pack(side='left', pady=20)
    open_checkbox = Checkbutton(convert_frame, text='转换后自动打开', variable=open_after_conversion)
    open_checkbox.pack(side='left', padx=10)
    convert_frame.pack()

    # 添加用于显示状态的 Label，并确保其显示在开始转换按钮正下方
    status_label = Label(root, text='', font=('Arial', 24))
    status_label.pack(pady=5)

    # 添加用于显示结果的 Label
    result_label = Label(root, text='', wraplength=380, justify='left')
    result_label.pack(pady=10)

    # 添加用于显示日志的 Label，固定在窗口底部
    log_label = Label(root, text='', wraplength=380, justify='left')
    log_label.pack(side='bottom', pady=10)

    root.mainloop()